/**
  ************************************* Copyright ******************************
  * FileName   : screen.c
  * Version    : v1.0
  * Author     : yychao
  * Date       : 2023-06-16
  * Description:
  * Function List:
  	1. ....
  	   <version>:
  <modify staff>:
  		  <data>:
   <description>:
  	2. ...
  ******************************************************************************
 */

#include <rtthread.h>
#include "screen.h"
#include "usart.h"
#include "stddef.h"
#include "string.h"
#include "log.h"
#include "rtc.h"
#include "lfs_port.h"
#include "io_ctrl.h"
const uint8_t chk_array[6]= {0x5a, 0xa5, 0x03, 0x82, 0x4f, 0x4b};

extern struct rt_messagequeue static_mq1;
extern struct rt_mutex static_mutex0;
extern struct rt_semaphore static_sem1;
struct protocol screen_prot;
struct screen_para screen_para_st;
struct screen_ctrl screen_ctrl_st = {0x00};

void screen_deal(usart_cache* recv)
{
    screen_adv(&recv->data[3], recv->cnt - 3);
}

void screen_adv(uint8_t *data, uint16_t len)
{
    uint8_t cache[64] = { 0x00 };
    if ((len - 3) != data[2]) {
        for (uint16_t j = 0; j < len; j++) {
            LOG_ERROR("%x ", data[j]);
        }
        LOG_ERROR("\r\n");
        LOG_ERROR("Stick the data package!\r\n");
        for (uint16_t i = 0; i < len;) {
            if ((data[i] == 0x5A) && (data[i + 1] == 0xA5)) {
                memset(&cache[0], 0x00, 64);
                memcpy(&cache[0], &data[i], data[i + 2] + 3);
                screen_frame(&cache[0], data[i + 2] + 3);
                i = i + data[i + 2] + 3;
            } else {
                i++;
            }
        }
    } else {
        screen_frame(&data[0], len);
    }
}

void screen_frame(uint8_t *data, uint16_t len)
{
    uint8_t type = 0;
    if(screen_para_st.wanter_flag == 1) {
        if(0 == memcmp(&data[0], &screen_para_st.wanter_data[0], len)) {
            rt_sem_release(&static_sem1);
            screen_para_st.wanter_flag = 0;
            type = 1;
        } else {
            /**/
            type = 2;
        }
    } else {
        rt_mq_send(&static_mq1, &data[0], SCREEN_MQ_BUF_SIZE);
        type = 3;
        for (uint16_t i = 0; i < len; i++) {
            LOG_DEBUG("%02x ", data[i]);
        }
        LOG_DEBUG("[RxLen %d Type %d] \r\n", len, type);
    }
}


void Screen_OutQueue(void)
{
    uint8_t buf[SCREEN_MQ_BUF_SIZE];
    uint16_t cnt = 0;
    if(0 == rt_mq_recv(&static_mq1,&buf[0], sizeof(buf), 0)) {
        screen_touch(&buf[0],128);
    }
}
uint8_t screen_touch(uint8_t *data, uint16_t len)
{

    uint16_t maxdate = 0;
    uint16_t temp = 0;

    screen_prot.head = ((uint16_t) data[0] << 8) | (data[1]);
    screen_prot.len = data[2];
    screen_prot.cmd = data[3];
#ifdef SCREEN_CRC
    screen_prot.crc = ((uint16_t) data[len - 2] << 8) | (data[len - 1]);
#endif
    screen_prot.addr = ((uint16_t) data[4] << 8) | (data[5]);
    screen_prot.byte = data[6];
    switch(screen_prot.byte) {
    case 1:
        screen_prot.value_16 = ((uint16_t) data[7] << 8) | (data[8]);
        break;
    case 2:
        screen_prot.value_32 = ((uint32_t) data[7] << 8 * 3) | (data[8] << 8 * 2)
                               | (data[9] << 8) | (data[10]);
        break;
    default:
        NULL;
    }
    if (PROT_HEAD != screen_prot.head) {
        screen_prot.err_code = head_err;
        goto err_ret;
    }
#if 0
    if ((len - 3) != screen_prot.len) {
        screen_prot.err_code = len_err;
        goto err_ret;
    }
#endif
    //#define SCREEN_CRC
#ifdef SCREEN_CRC
    if(CRC16_Modbus(&data[0], len - 2) != screen_prot.crc) {
        screen_prot.err_code = crc_err;
        goto err_ret;
    }
#endif
    switch (screen_prot.cmd) {
    case Touch:
        switch(screen_prot.addr) {
        case T_LED:
            switch(screen_prot.value_16) {
            case T_RED_LED:
                LOG_DEBUG("Switch RED-LED\r\n");
                if(screen_ctrl_st.red_led == 0) {
                    temp = PIC_RED_LED_ON;
                    screen_write(P_RED_LED, (uint16_t*)&temp, 1);
                    screen_ctrl_st.red_led = 1;
                } else {
                    temp = PIC_RED_LED_OFF;
                    screen_write(P_RED_LED, (uint16_t*)&temp, 1);
                    screen_ctrl_st.red_led = 0;
                }
                break;
            case T_YELLOW_LED:
                LOG_DEBUG("Switch YEL-LED\r\n");
                if(screen_ctrl_st.yellow_led == 0) {
                    temp = PIC_YEL_LED_ON;
                    screen_write(P_YELLOW_LED, (uint16_t*)&temp, 1);
                    screen_ctrl_st.yellow_led = 1;
                } else {
                    temp = PIC_YEL_LED_OFF;
                    screen_write(P_YELLOW_LED, (uint16_t*)&temp, 1);
                    screen_ctrl_st.yellow_led = 0;
                }
                break;
            case T_BLUE_LED:
                LOG_DEBUG("Switch BLU-LED\r\n");
                if(screen_ctrl_st.blue_led == 0) {
                    temp = PIC_BLU_LED_ON;
                    screen_write(P_BLUE_LED, (uint16_t*)&temp, 1);
                    screen_ctrl_st.blue_led = 1;
                } else {
                    temp = PIC_BLU_LED_OFF;
                    screen_write(P_BLUE_LED, (uint16_t*)&temp, 1);
                    screen_ctrl_st.blue_led = 0;
                }
                break;
            }
            break;
        default:
            NULL;
        }
        break;
    case Write:
        break;
    default:
        screen_prot.err_code = cmd_err;
        goto err_ret;
    }
    return OK;
err_ret:
    LOG_ERROR("Format error: err-code %d \r\n", screen_prot.err_code);
    return FAILED;
}

uint8_t screen_analyze(struct screen_ctrl* data)
{






}
uint8_t screen_write(uint16_t addr, uint16_t *value, uint16_t num)
{
    if( 0 != rt_mutex_take(&static_mutex0, 1000)) {
        LOG_ERROR("rt_mutex_take static_mutex0 Failed!\r\n");
        rt_mutex_release(&static_mutex0);
        return FAILED;
    }
    memset(&screen_para_st.trans_data[0], 0x00, 128);
    screen_para_st.trans_data[0] = PROT_HEAD >> 8;
    screen_para_st.trans_data[1] = (uint8_t) PROT_HEAD;
    screen_para_st.trans_data[2] = 0x03 + num * 2;
    screen_para_st.trans_data[3] = Write;
    screen_para_st.trans_data[4] = addr >> 8;
    screen_para_st.trans_data[5] = (uint8_t) addr;
    for (uint8_t i = 0; i < num; i++) {
        screen_para_st.trans_data[6 + i * 2] = value[0 + i] >> 8;
        screen_para_st.trans_data[7 + i * 2] = (uint8_t) value[0 + i];
    }

    screen_para_st.trans_len = 6 + num * 2;
    screen_para_st.wanter_flag = 1;
    screen_para_st.ms = 300;
    screen_para_st.wanter_data[0] = 0x00;
    memcpy(&screen_para_st.wanter_data[0], &chk_array[0], sizeof(chk_array));
    if(0 != screen_data_check(&screen_para_st)) {
        LOG_ERROR("Screen Check receive Failed!\r\n");
        rt_mutex_release(&static_mutex0);
        return FAILED;
    }
    rt_mutex_release(&static_mutex0);
    return OK;
}

uint8_t screen_data_check(struct screen_para* st)
{
    uint8_t ret = 0;
    usart_trans(USART2, &st->trans_data[0], st->trans_len);
#if 1
    for (uint16_t i = 0; i < st->trans_len; i++) {
        LOG_DEBUG("%02x ", st->trans_data[i]);
    }
#endif
    LOG_DEBUG("[TxLen %d] \r\n", st->trans_len);
    if(0 == rt_sem_take(&static_sem1, st->ms))
    {
        ret = 0;
    } else {
        if(st->wanter_flag == 0) {
            ret = 0;
        } else {
            ret = 1;
        }
    }
    return ret;
}
uint8_t screen_page(uint16_t page)
{
    uint16_t cache[2] = { 0x5A01, 0xffff};
    cache[1] = page;
    if(0 != screen_write(0x0084,(uint16_t*)&cache[0], 2)) {
        return FAILED;
    } else {
        return OK;
    }
}
uint8_t screen_ini(void)
{
    uint16_t temp = 0;
#if 1
    while(0 != screen_page(P_CONNECT)) {
    }
    rt_thread_delay(1000);

    temp = PIC_RED_LED_OFF;
    screen_write(P_RED_LED, (uint16_t*)&temp, 1);
    temp = PIC_YEL_LED_OFF;
    screen_write(P_YELLOW_LED, (uint16_t*)&temp, 1);
    temp = PIC_BLU_LED_OFF;
    screen_write(P_BLUE_LED, (uint16_t*)&temp, 1);
#endif
    while(0 != screen_page(P_INITIAL)) {
    }
    rt_thread_delay(1000);
#if 0
    while(0 != screen_page(P_MAIN)) {
    }
    rt_thread_delay(1000);
#endif
}
